package com.zh.oauth.controller;


import com.alibaba.fastjson.JSON;
import com.zh.common.entity.JSONResult;
import com.zh.common.entity.Oauth;
import com.zh.common.entity.Result;
import com.zh.common.util.OkHttpClientUtil;
import com.zh.common.annotaion.CurrentUser;
import com.zh.common.constans.AuthConstant;
import com.zh.common.entity.ElecMenu;
import com.zh.oauth.entity.ElecAuth;
import com.zh.oauth.entity.ElecRole;
import com.zh.oauth.entity.ElecUser;
import com.zh.oauth.service.ElecUserService;
import com.zh.oauth.util.MenuUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.Principal;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * code is far away from bug with the animal protecting
 * ┏┓　　　┏┓
 * ┏┛┻━━━┛┻┓
 * ┃　　　　　　　┃
 * ┃　　　━　　　┃
 * ┃　┳┛　┗┳　┃
 * ┃　　　　　　　┃
 * ┃　　　┻　　　┃
 * ┃　　　　　　　┃
 * ┗━┓　　　┏━┛
 * 　　┃　　　┃神兽保佑
 * 　　┃　　　┃代码无BUG！
 * 　　┃　　　┗━━━┓
 * 　　┃　　　　　　　┣┓
 * 　　┃　　　　　　　┏┛
 * 　　┗┓┓┏━┳┓┏┛
 * 　　　┃┫┫　┃┫┫
 * 　　　┗┻┛　┗┻┛
 *
 * @Description:
 * @Author: Li.HuiNeng
 * @Create in: 2019-09-20 10:50
 * @Version: 1.0.1
 */

@Api(value = "LoginController", tags = "登录控制器")
@RestController
@RequestMapping("/login")
public class LoginController {

    private static final Logger log = LoggerFactory.getLogger(LoginController.class);

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ElecUserService service;


    @GetMapping("/user")
    public Principal user(@CurrentUser Principal principal) {
        return principal;
    }


    // todo 此处将用户认证与获取权限分离开来
    //  登录接口只认证用户相关信息，权限认证另外发送请求获取,这么做是为了根据不同客户端点进行不同的方式验证
    @PostMapping("/account")
    @ResponseBody
    public JSONResult<Object> login(@ApiParam(name = "user", value = "用户实体信息") @RequestBody ElecUser user, HttpServletRequest req, HttpServletResponse res) throws Exception {
        JSONResult<Object> jsonResult = new JSONResult<>();
        // 验证用户信息
        try {
            /**
             * @JSONResult
             * @Result
             * JsonResult外层返回体表示服务器请求状态
             */
            jsonResult.setSuccess(AuthConstant.boolF);
            jsonResult.setMessage(HttpStatus.OK.name());
            res.setContentType("text/html;charset=utf-8");
            res.setCharacterEncoding("utf-8");
            // 设置请求体
            Map<String, String> bodyMap = new HashMap<>();
            bodyMap.put("username", user.getUserLoginName());
            bodyMap.put("password", user.getUserPassword());
            bodyMap.put("scope", user.getScope());
            bodyMap.put("grant_type", user.getGrantType());
            // 设置请求头
            Map<String, String> headMap = new HashMap<>();
            headMap.put("Content-Type", "application/x-www-form-urlencoded");
            headMap.put("Authorization", req.getHeader("Authorization"));
            // 通过 HTTP 客户端请求登录接口
            Response response = OkHttpClientUtil.getInstance().postData(AuthConstant.URL_OAUTH_TOKEN, bodyMap, headMap);
            if (!response.isSuccessful()) {
                jsonResult.setSuccess(false);
                jsonResult.setCode(response.code());
                jsonResult.setMessage(response.message().equals("") ? "该用户不存在，请检查账户名是否正确!" : response.message());
                return jsonResult;
            }
            String jsonString = Objects.requireNonNull(response.body()).string();
            HashMap jsonMap = JSON.parseObject(jsonString, HashMap.class);
            List<ElecMenu> menuList = JSON.parseArray(JSON.toJSONString(redisTemplate.opsForValue().get(user.getUserLoginName() + AuthConstant.REDIS_WEB_MENU_KEY)), ElecMenu.class);
            List<String> authList = JSON.parseArray(JSON.toJSONString(redisTemplate.opsForValue().get(user.getUserLoginName() + AuthConstant.REDIS_WEB_SERVE_KEY)), String.class);
            ElecUser userInfo = JSON.parseObject(JSON.toJSON(redisTemplate.opsForValue().get(user.getUserLoginName() + AuthConstant.USER_INFO)).toString(), ElecUser.class);
            jsonMap.put("user", userInfo);
            jsonMap.put("menu", menuList);
            jsonMap.put("auth", authList);
            jsonResult.setSuccess(AuthConstant.boolT);
            jsonResult.setData(jsonMap);
        } catch (IOException e) {
            jsonResult.setCode(HttpStatus.SERVICE_UNAVAILABLE.value());
            jsonResult.setSuccess(AuthConstant.boolF);
            jsonResult.setMessage(e.getLocalizedMessage());
            e.printStackTrace();
        }
        return jsonResult;
    }


    @PostMapping("/mobile")
    @ResponseBody
    public JSONResult<Object> loginByMob(@RequestBody ElecUser user, HttpServletRequest req, HttpServletResponse res) throws Exception {
        JSONResult<Object> jsonResult = new JSONResult<>();
        // 对比缓存中的验证码与提交的验证码是否相同
        Object o = redisTemplate.opsForValue().get(user.getUserMobile());
        if (Objects.isNull(o)) {
            jsonResult.setSuccess(AuthConstant.boolF);
            jsonResult.setMessage("验证码过期，请重新获取.");
            return jsonResult;
        } else {
            String cap = o.toString();
            if (!cap.equals(user.getCaptcha())) {
                jsonResult.setCode(HttpStatus.SERVICE_UNAVAILABLE.value());
                jsonResult.setSuccess(AuthConstant.boolF);
                jsonResult.setMessage("验证码不正确.");
                return jsonResult;
            } else {
                Map<String, Object> result = new HashMap<>();
                // 验证用户信息
                res.setContentType("text/html;charset=utf-8");
                res.setCharacterEncoding("utf-8");
                // 设置请求体
                Map<String, String> bodyMap = new HashMap<>();
                bodyMap.put("scope", user.getScope());
                bodyMap.put("grant_type", user.getGrantType());
                // 设置请求头
                Map<String, String> headMap = new HashMap<>();
                headMap.put("Content-Type", "application/x-www-form-urlencoded");
                headMap.put("Authorization", req.getHeader("Authorization"));
                // 通过 HTTP 客户端请求登录接口
                Response response = OkHttpClientUtil.getInstance().postData(AuthConstant.URL_OAUTH_TOKEN, bodyMap, headMap);
                if (!response.isSuccessful()) {
                    jsonResult.setSuccess(AuthConstant.boolF);
                    jsonResult.setMessage("请检查授权码是否正确");
                    return jsonResult;
                } else {
                    String jsonString = Objects.requireNonNull(response.body()).string();
                    HashMap jsonMap = JSON.parseObject(jsonString, HashMap.class);
                    ElecUser elecUser = service.getUserInfoByMobile(user.getUserMobile());
                    if (Objects.isNull(elecUser)) {
                        jsonResult.setSuccess(AuthConstant.boolF);
                        jsonResult.setMessage("改手机号不存在对应用户，请检查手机号码是否正确");
                        return jsonResult;
                    }
                    List<ElecMenu> menuList = JSON.parseArray(JSON.toJSONString(redisTemplate.opsForValue().get(elecUser.getUserLoginName() + AuthConstant.REDIS_WEB_MENU_KEY)), ElecMenu.class);
                    List<String> authList = JSON.parseArray(JSON.toJSONString(redisTemplate.opsForValue().get(elecUser.getUserLoginName() + AuthConstant.REDIS_WEB_SERVE_KEY)), String.class);
                    ElecUser userInfo = JSON.parseObject(JSON.toJSON(redisTemplate.opsForValue().get(elecUser.getUserLoginName() + AuthConstant.USER_INFO)).toString(), ElecUser.class);
                    jsonMap.put("user", userInfo);
                    jsonMap.put("menu", menuList);
                    jsonMap.put("auth", authList);
                    jsonResult.setData(jsonMap);
                    jsonResult.setSuccess(AuthConstant.boolT);
                    jsonResult.setMessage("登陆完成!");
                    // 删除验证码信息
                    redisTemplate.delete(user.getUserMobile());
                    return jsonResult;
                }
            }
        }
    }


    @ApiOperation(value = "/logout", notes = "退出登录")
    @PostMapping("/logout")
    public JSONResult<Object> logout(HttpServletRequest request, HttpServletResponse response) {
        JSONResult<Object> jsonResult = new JSONResult<>();
        try {
            String uName = request.getParameter("userName");
            // 清除缓存数据
            redisTemplate.delete(uName + AuthConstant.REDIS_WEB_MENU_KEY);
            redisTemplate.delete(uName + AuthConstant.REDIS_WEB_SERVE_KEY);
            redisTemplate.delete(uName + AuthConstant.USER_INFO);
            redisTemplate.delete(uName + AuthConstant.USER_ROLE);
            redisTemplate.delete(uName + AuthConstant.REDIS_AUTH_TREE);
            new SecurityContextLogoutHandler().logout(request, null, null);
            jsonResult.setMessage("退出成功!");
            jsonResult.setSuccess(true);
        } catch (Exception e) {
            jsonResult.setMessage("退出异常:" + e.getLocalizedMessage());
            jsonResult.setSuccess(false);
            e.printStackTrace();
        }
        return jsonResult;
    }


//
//    @GetMapping("/getAuth")
//    @ApiOperation(value = "/getAuth" , notes = "获取权限列表" )
//    public JSONResult<Object> getUserAuth(Long userId){
//        JSONResult<Object> jsonResult = new JSONResult<>();
//        try {
//            Map map = elecUserService.getUserAuth(userId);
//            jsonResult.setSuccess(true);
//            jsonResult.setData(map);
//        } catch (Exception e) {
//            e.printStackTrace();
//            jsonResult.setSuccess(false);
//            jsonResult.setMessage(e.getLocalizedMessage());
//        }
//        return jsonResult;
//    }
//
//    @GetMapping("/getRoleMenu")
//    @ApiOperation(value = "/getRoleMenu" , notes = "获取菜单列表" )
//    public JSONResult<Object> getRoleMenu(Integer userType, String roleNo){
//        JSONResult<Object> jsonResult = new JSONResult<>();
//        try {
//            Map map = elecUserService.getUserAuthByRoleNo(userType,roleNo);
//            jsonResult.setSuccess(true);
//            jsonResult.setData(map);
//        } catch (Exception e) {
//            e.printStackTrace();
//            jsonResult.setSuccess(false);
//            jsonResult.setMessage(e.getLocalizedMessage());
//        }
//        return jsonResult;
//    }


}
